<?php
/**********************************************************************************
 
	Creates a customizable table to be displayed in a browser.
 
 	Copyright (C) 2010 Benjamin Thomas
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 	Author: Benjamin Thomas
	Email: thomas.ben@gmail.com
	Created: 05.21.10
 	Revised: 07.04.10

 	Calls: None.
 
 **********************************************************************************
 */

 //This class should not be called directly.

class Table {
	protected $title;
	protected $headings;
	protected $align = null;
	protected $padding = 6;
	protected $data;
	protected $collapse = "";
	protected $hidden = false;
	protected $sessions = false;
	protected $style;
	protected $rowclass;
	protected $rowclasspointer;
	protected $id;
	protected $link;
	protected $color = array("B8CCE4","DBE5F1");
	protected $margin = array("top" => 0, "left" => 'auto', "right" => 'auto', "bottom" => 10);
	
	public function __construct($title = "", $data = "", $headings = "") {	
		$this->style = array('width' => '95%', "padding" => "3px 1px 1px 1px");
		if ($title != "") {
			$this->setTitle($title);
		}
		if ($data != "") {
			$this->addData($data);
		} else {
			$this->data = array();	
		}
		if ($headings != "") {
			$this->setHeadings($headings);
		} else {
			$headings = array();
		}
	}
	
	public function __decontruct() {
		unset($data);
	}
	
	public function addData($arr) {
		if (!is_array($arr)) {
			$this->data[] = array($arr);
		} else {
			foreach ($arr as &$val) {
				if (!is_array($val)) {
					$val = array($val);
				}
				$this->data[] = $val;
			}
		}
	}
	
	public function setId($id) {
		$this->id = $id;
	}
	
	public function useSessions($val = true) {
		$this->sessions = $val;
		$key = 'show_' . $this->collapse;
		if (isset($_COOKIE[$key]) && $_COOKIE[$key] == 'false') {
			$this->setHidden();
		}
	}
	
	public function resetStyle() {
		unset($this->style);
		$this->style = array();
	}	
	
	public function setStyle($mixed) {
		if (is_array($mixed)) {
			foreach($mixed as $key => $val) {
				$this->style[$key] = $val;
			}
		} else {
			list($key, $val) = explode(":", $mixed);
			$this->style[$key] = $val;
		}
	}
	
	public function setRowClass($arr) {
		if (!is_array($arr)) {
			echo "Non-array variable passed to setRowClass. ($arr)";
			return false;
		}
		$this->rowclasspointer = array ( 0 => 0);
		$this->rowclass = array(0 => $arr);
	}
	
	public function setMultiRowClass($arr) {
		$this->rowclasspointer = array_fill(0, count($arr), 0);
		$this->rowclass = $arr;
	}
	
	public function setHidden() {
		$this->hidden = true;
		$_COOKIE["show_" . $this->collapse] = "false";
	}
	
	public function setPadding($int) {
		$this->padding = $int;
	}
	
	public function setAllMargins($val) {
		$this->setMargin($val, 'left');
		$this->setMargin($val, 'right');	
		$this->setMargin($val, "top");
		$this->setMargin($val, 'bottom');
	}
		
	public function setMargin($val, $key) {
		//append px to all integers
		if (is_int($val)) {
			$val .= "px";
		}	
		$this->margin[$key] = $val;
	}
	
	public function setVertMargin($val) {
		$this->setMargin($val, "left");
		$this->setMargin($val, "right");
	}
	
	public function setHorizMargin($val) {
		$this->setMargin($val, "top");
		$this->setMargin($val, "bottom");
	}
	
	public function setHeadings($arr) {
		$this->headings = $arr;
	}
	
	public function setTitle($str) {
		$this->title = $str;
	}	
	
	public function showLinks($link, $page, $limit, $total) {
		$this->link = array('link' => $link, 'page' => $page, 'limit' => $limit, 'total' => $total);
	}
	
	public function setAlign($mixed) {
		if (!is_array($mixed)) {
			$tmp = $mixed; 
			$mixed = array();
		} else {
			$tmp = $mixed[ count($mixed) - 1 ];
		}
		while ( count($mixed) <  count($this->data[0]) ) {
			$mixed[] = $tmp;
		}
		$this->align = $mixed;
	}
	
	public function setCollapse($id) {
		$this->id = $this->collapse = $id;
	}
		
	public function printTable() {
		if ($this->headings) {
			$columns = count($this->headings); 
		} else {
			$columns = count($this->data[0]); 
		}
		if ($this->align == null) {
			$this->setAlign("center");
		}
		
		//Create the table and the title
		


		$style = $this->getScript() . " text-align:right;";
		if ($this->collapse != "") { 
			$style .= 'padding: 3px 1px 1px 1px;';
		}
		if (!$this->link) {
			$style .= 'background-color: 4578D6; -moz-border-radius : 10px; -webkit-border-radius: 10px';
		}
		echo '<div id="blah" style="' . $style . '">';	
		
		if (isset($this->link)) {
			$this->printNumberLinks();
		}
		
		if ($this->title != "") {
			$style = "padding: {$this->padding}px;";
			if ($this->collapse) {
				$style .= '	cursor: pointer; -moz-border-radius: 10px;-webkit-border-radius: 10px;';
			} else {
				$style .= ' background-color: 4578D6;';
				$style .= ' -moz-border-radius-topleft:10px; -webkit-border-top-left-radius:10px;';
				if (!$this->link) {
					$style .= ' -moz-border-radius-topright:10px; -webkit-border-top-right-radius:10px;';
				}
			}
			echo '<div class="title" id="btn' . $this->collapse . '" style="' . $style . '">' .  $this->title . '</div>';
		}
		

		$style = "width: 100%;";
		if ($this->hidden) {
			$style .= "display: none;";
		}
		echo '<table id="' . $this->id . '" align="center" cellspacing="0" cellpadding="' . $this->padding . '" style="' . $style . '">';

		//Create the headings
		if ( count($this->headings) > 0) {
			echo '<thead>';
			echo "<tr>";
			reset($this->headings);
			$i = 0;
			foreach($this->headings as &$val) {
				$style = "";
				//Round the corners if the title is not present.
				if (!$this->title) {
					if ($i == 0) {
						$style .= " -moz-border-radius-topleft:10px; -webkit-border-top-left-radius:10px;";
					}
					if ($i == ($columns - 1) && !$this->link) {
						$style .= " -moz-border-radius-topright:10px; -webkit-border-top-right-radius:10px;";
					}
				}
				print '<th style="' . $style . '">' . $val . '</td>';
				$i++;
			}
			echo '</tr>';
			echo '</thead>';
		}
		echo '<tbody>';
		$switch = true;
		$classswitch = true;
		$lastclassset = 0;
		//Create all the data rows	
		reset($this->data);	
		$count = 0;
		foreach ($this->data as &$row) {
			$switch = !$switch;
			if ($this->rowclass) {
				if (count($this->rowclass) > 1) { $set = $row['set']; } else { $set = 0; }
				$class = $this->incrementClass($set);					
				$rowstyle = '';
			} else {
				$class = "row";
				$rowstyle = 'background-color: ' .$this->color[intval($switch)] . '; color: black;';
			}
			print '<tr class="' . $class . '">' . "\n";
			$i = 0;
			unset($row['set']);
			foreach($row as $num => &$val) {
				$style = $rowstyle;
				if ($this->title) {
					if ($count == 0 && $i == 0) {
						//$style .= " -moz-border-radius-topleft:10px; -webkit-border-top-left-radius:10px;";
					}
					if ($count == 0 && $i == ($columns - 1) ) {
						//$style .= " -moz-border-radius-topright:10px; -webkit-border-top-right-radius:10px;";
					}
					if ($i == 0 && $count == (count($this->data) - 1)) {
						$style .= " -moz-border-radius-bottomleft:10px; -webkit-border-bottom-left-radius:10px;";
					}
					if ($count == count($this->data) - 1 && $i == count($row) - 1 && !$this->link) {
						$style .= " -moz-border-radius-bottomleft:10px; -webkit-border-bottom-right-radius:10px;";
					}
				}
				$align = '';
				if ($this->align) {
					$align = " align=\"{$this->align[$i]}\"";
				}
				$span = '';
				if ( count($row) < $columns && count($row) == $num + 1) {
					$span = 'colspan="' . ($columns - count($row) + 1) . '"';
				}
				$debug = "($num)";
				print '<td ' . $align . ' ' . $span . ' style="' . $style . '">' . $val . '</td>';
				$i++;
			}
			print '</tr>' . "\n";
			$count++;
		}			
		echo '</tbody>';
		echo '</table>';
		if (isset($this->link)) {
			$this->printNumberLinks(true);
		}
		echo '</div>';
		if ($this->collapse) {
			$btn = "$(\"#btn{$this->collapse}\")";
			$container = "$(\"#{$this->collapse}\")";
			print '<script>' . "\n";
			$showCookie = "";
			$hideCookie = "";
			if ($this->sessions) {
				$cookie = "show_" . $this->collapse;
				$showCookie = "$.cookie('{$cookie}', 'true', { expires: 7 });";
				$hideCookie = "$.cookie('{$cookie}', 'false', { expires: 7 });";
			}			
			print "{$btn}.click( function () { if ( {$container}.is(\":visible\") ) { {$container}.hide(); {$hideCookie} } else { {$container}.show(); {$showCookie} } });\n";
			print '</script>';
		}
	}
	
	protected function incrementClass($set) {
		$tmp = $this->rowclass[$set][$this->rowclasspointer[$set]];
		if (++$this->rowclasspointer[$set] >= count($this->rowclass[$set])) { $this->rowclasspointer[$set] = 0; }
		$sets = count($this->rowclass);
		if ($sets > 1) {
			//Reset all other sets to their first value
			for ($i = 0; $i < $sets; $i++) {
				if ($i != $set) { $this->rowclasspointer[$i] = 0; }
			}
		}
		return $tmp;
	}

	protected function getScript() {
		$str = "";
		while  (list($key,$val) = each($this->style)) {
			$str .= "$key : $val; ";
		}
		$str .= $this->getMarginScript();
		return $str;
	}
		
	protected function printNumberLinks($b = false) {
		$link = $this->link['link']; $page = $this->link['page']; $limit = $this->link['limit']; $total = $this->link['total'];
		if (!$total) { $total = 0; }
		$class = "pageSelect";
		if ($b) { $class .= ' roundBottom'; } else { $class .= ' roundTop'; }
		echo '<span class="' . $class . '">';
		$totalpages = ceil($total / $limit);
		if ($page > 2 && $totalpages > 2) { echo '<a href="' . $link . '&p=1"> &lt;&lt;First </a>'; }
		if ($page > 1) { echo '<a href="' . $link . '&p=' . ($page-1) . '"> &lt; Prev </a>'; }
		$start = ($page-1) * $limit + 1;
		$end = $page * $limit;
		if ($end > $total) { $end = $total; }
		echo "$start - $end of $total";
		if ($page < $totalpages) { echo '<a href="' . $link . '&p=' . ($page + 1) . '"> Next&gt; </a>'; }
		if ($page < $totalpages && $page != $totalpages - 1) { echo '<a href="' . $link . '&p=' . $totalpages . '"> Last&gt;&gt; </a>'; }
		echo '</span>';
	}
	
	protected function getMarginScript() {
		$str = "";
		if ($this->margin['top'] != "") {
			$str .= "margin-top:{$this->margin['top']}; ";
		}
		if ($this->margin['left'] != "") {
			$str .= "margin-left:{$this->margin['left']}; ";
		}
		$str .= "margin-bottom:{$this->margin['bottom']}; ";
		if ($this->margin['right'] != "") {
			$str .= "margin-right:{$this->margin['right']}; ";
		}
		return $str;
	}
}
